/*****************************************************************
Wowengine - v0.1

File: wen_directInput.cpp
Creation date: 2009-08-05
*****************************************************************/

/****************************************************************/
#include "wen_directInput.h"
//----------------------------------------------------------------
using namespace wen;
/****************************************************************/

//----------------------------------------------------------------
DirectInput::DirectInput(HINSTANCE kInstance, HWND kWnd):
m_pkKeyboardObj(NULL),
m_pkMouseObj(NULL),
m_pkKeyboardDev(NULL),
m_pkMouseDev(NULL),
m_kAppInstance(kInstance),
m_kWindowHandler(kWnd)
{
}
//----------------------------------------------------------------
DirectInput::~DirectInput()
{
	Unacquire();
	Deinit();
}
//----------------------------------------------------------------
bool DirectInput::Init()
{
	static HRESULT hr;

	/*Inicializamos el Teclado*/
	//Cargamos el objeto de teclado
	hr = DirectInput8Create(m_kAppInstance, 
							DIRECTINPUT_VERSION, 
							IID_IDirectInput8,
							(void**)&m_pkKeyboardObj, 
							NULL );

	if (FAILED(hr))
	{
		return false;
	}

	//Creamos el device
	hr = m_pkKeyboardObj->CreateDevice(GUID_SysKeyboard, &m_pkKeyboardDev, NULL);

	if (FAILED(hr))
	{
		return false;
	}

	//set the keyboard data format (no queres saberlo)
	hr = m_pkKeyboardDev->SetDataFormat(&c_dfDIKeyboard);

	if (FAILED(hr))
	{
		return false;
	}

	//Asigna exclusividad en caso de estar en full screen (Falta implementar)
	hr = m_pkKeyboardDev->SetCooperativeLevel(m_kWindowHandler, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);

	if (FAILED(hr))
	{
		return false;
	}

	//Adquirimos el keyboard
	hr = m_pkKeyboardDev->Acquire();

	if (FAILED(hr))
	{
		return false;
	}

	/*Inicializamos el Mouse*/
	//Cargamos el objeto de mouse
	hr = DirectInput8Create(m_kAppInstance, 
							DIRECTINPUT_VERSION, 
							IID_IDirectInput8,
							(void**)&m_pkMouseObj,	
							NULL );
    
	if (FAILED(hr))
	{
		return false;
	}

	//Creamos el device
	hr = m_pkMouseObj->CreateDevice(GUID_SysMouse, &m_pkMouseDev, NULL);

	if (FAILED(hr))
	{
		return false;
	}

	//set the mouse data format (no queres saberlo)
	hr = m_pkMouseDev->SetDataFormat(&c_dfDIMouse);

	if (FAILED(hr))
	{
		return false;
	}

	//Asigna exclusividad en caso de estar en full screen (Falta implementar)
	hr = m_pkMouseDev->SetCooperativeLevel(m_kWindowHandler, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);

	if (FAILED(hr))
	{
		return false;
	}

	// acquire the mouse
	hr = m_pkMouseDev->Acquire();

	if (FAILED(hr))
	{
		return false;
	}

	return true;
}
//----------------------------------------------------------------
void DirectInput::Update()
{
	Reacquire();
	UpdateMouse();
	UpdateKeyboard();
}
//----------------------------------------------------------------
void DirectInput::Deinit()
{
    if (m_pkKeyboardObj)					// if DirectInput Object One exist
    {
        if (m_pkKeyboardDev)				// if KeyboardDevice Object exist
        {
            m_pkKeyboardDev->Unacquire();	// then unacquire it
            m_pkKeyboardDev->Release();		// and Release it
            m_pkKeyboardDev = NULL;			// and NULL the pointer
        }
        m_pkKeyboardObj->Release();			// Release the DirectInput Object One
        m_pkKeyboardObj = NULL;				// and NULL the pointer
    }

    if (m_pkMouseObj)						// if DirectInput Object Two exist
    {
        if (m_pkMouseDev)					// if MouseDevice Object exist
        {
            m_pkMouseDev->Unacquire();		// then unacquire it
            m_pkMouseDev->Release();		// and Release it
            m_pkMouseDev = NULL;			// and NULL the pointer
        }
        m_pkMouseObj->Release();			// Release the DirectInput Object Two
        m_pkMouseObj = NULL;				// and NULL the pointer
    }
}
//----------------------------------------------------------------
void DirectInput::Reset()
{
	// resets all the devices status buffers
	Input::Reset();
	ZeroMemory(&m_kMouseState, sizeof(m_kMouseState));
}
//----------------------------------------------------------------
void DirectInput::Acquire()
{
	// get the keyboard device state
	memcpy(m_aucKeyPrevBuffer, m_aucKeyBuffer, 256);
	ZeroMemory(&m_aucKeyBuffer, sizeof(m_aucKeyBuffer));
	m_pkKeyboardDev->GetDeviceState(sizeof(m_aucKeyBuffer), &m_aucKeyBuffer);

	// get the mouse device state
	ZeroMemory(&m_kMouseState, sizeof(m_kMouseState));
	m_pkMouseDev->GetDeviceState(sizeof(m_kMouseState), &m_kMouseState);

	// Update the mouse absolute position
	m_alMouseScreenAbsPos[POS_X] += m_kMouseState.lX;
	m_alMouseScreenAbsPos[POS_Y] -= m_kMouseState.lY;
	m_alMouseScreenAbsPos[POS_Z] += m_kMouseState.lZ;

	// set the mouse relative position
	m_alMouseRelPos[POS_X] = m_kMouseState.lX;
	m_alMouseRelPos[POS_Y] = m_kMouseState.lY;
	m_alMouseRelPos[POS_Z] = m_kMouseState.lZ;

	// updates the mouse button states
	m_aucMouseBut[MB_1] = m_kMouseState.rgbButtons[MB_1] & 0x80;
	m_aucMouseBut[MB_2] = m_kMouseState.rgbButtons[MB_2] & 0x80;
	m_aucMouseBut[MB_3] = m_kMouseState.rgbButtons[MB_3] & 0x80;
}
//----------------------------------------------------------------
void DirectInput::Reacquire()
{
	// reacquire all the input devices
	if (m_pkMouseDev)
	{
		m_pkMouseDev->Acquire();
	}
	if (m_pkKeyboardDev)
	{
		m_pkKeyboardDev->Acquire();
	}
	Acquire();
}
//----------------------------------------------------------------
void DirectInput::Unacquire()
{
	// unacquire all the input devices
	ZeroMemory(&m_aucKeyBuffer, sizeof(m_aucKeyBuffer));
	ZeroMemory(&m_kMouseState, sizeof(m_kMouseState));

	if (m_pkMouseDev)
	{
		m_pkMouseDev->Unacquire();
	}
	if (m_pkKeyboardDev)
	{
		m_pkKeyboardDev->Unacquire();
	}
}
//----------------------------------------------------------------